<template>
  <div>
    <el-card class="box-card">
      <div slot="header">
        <span>应用程序资源监控</span>
        <el-button type="text" icon="el-icon-refresh" style="float: right;padding: 0" @click="getMetrics">刷新</el-button>
      </div>
      <div>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-card class="box-card">
              <div slot="header">
                <span>JVM 资源监控</span>
              </div>
              <div>
                <p>
                  <span>总内存</span>
                  ({{metrics.gauges['jvm.memory.total.used'].value / 1048576 | numFilter2}}M / {{metrics.gauges['jvm.memory.total.max'].value / 1048576 | numFilter2}}M)
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.memory.total.used'].value * 100 / metrics.gauges['jvm.memory.total.max'].value | numFilter2"
                  status="success"
                ></el-progress>
                <p>
                  <span>堆内存</span>
                  ({{metrics.gauges['jvm.memory.heap.used'].value / 1048576 | numFilter2}}M / {{metrics.gauges['jvm.memory.heap.max'].value / 1048576 | numFilter2}}M)
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.memory.heap.used'].value * 100 / metrics.gauges['jvm.memory.heap.max'].value | numFilter2"
                  status="success"
                ></el-progress>
                <p>
                  <span>非堆内存</span>
                  ({{metrics.gauges['jvm.memory.non-heap.used'].value / 1048576 | numFilter2}}M / {{metrics.gauges['jvm.memory.non-heap.committed'].value / 1048576 | numFilter2}}M)
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.memory.non-heap.used'].value * 100 / metrics.gauges['jvm.memory.non-heap.committed'].value | numFilter2"
                  status="success"
                ></el-progress>
              </div>
            </el-card>
          </el-col>
          <el-col :span="8">
            <el-card class="box-card">
              <div slot="header" class="clearfix">
                <span>线程 (Total:{{metrics.gauges['jvm.threads.count'].value}})</span>
              </div>
              <div>
                <p>
                  <span>可运行</span>
                  {{metrics.gauges['jvm.threads.runnable.count'].value}}
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.threads.runnable.count'].value * 100 / metrics.gauges['jvm.threads.count'].value | numFilter2"
                  status="success"
                ></el-progress>
                <p>
                  <span>定时等待</span>
                  ({{metrics.gauges['jvm.threads.timed_waiting.count'].value}})
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.threads.timed_waiting.count'].value * 100 / metrics.gauges['jvm.threads.count'].value | numFilter2"
                  color="#FFC107"
                ></el-progress>
                <p>
                  <span>等待中</span>
                  ({{metrics.gauges['jvm.threads.waiting.count'].value}})
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.threads.waiting.count'].value * 100 / metrics.gauges['jvm.threads.count'].value | numFilter2"
                  color="#FFC107"
                ></el-progress>
                <p>
                  <span>阻塞中</span>
                  ({{metrics.gauges['jvm.threads.blocked.count'].value}})
                </p>
                <el-progress
                  :text-inside="true"
                  :stroke-width="18"
                  :percentage="metrics.gauges['jvm.threads.blocked.count'].value * 100 / metrics.gauges['jvm.threads.count'].value | numFilter2"
                  status="success"
                ></el-progress>
              </div>
            </el-card>
          </el-col>
          <el-col :span="8">
            <el-card class="box-card">
              <div slot="header" class="clearfix">
                <span>垃圾回收</span>
              </div>
              <div>
                <el-row class="item-row">
                  <el-col :span="18">标记清除次数</el-col>
                  <el-col :span="6">{{metrics.gauges['jvm.garbage.PS-MarkSweep.count'].value}}</el-col>
                </el-row>
                <el-row class="item-row">
                  <el-col :span="18">标记清除耗时</el-col>
                  <el-col :span="6">{{metrics.gauges['jvm.garbage.PS-MarkSweep.time'].value}}ms</el-col>
                </el-row>
                <el-row class="item-row">
                  <el-col :span="18">回收次数</el-col>
                  <el-col :span="6">{{metrics.gauges['jvm.garbage.PS-Scavenge.count'].value}}</el-col>
                </el-row>
                <el-row class="item-row">
                  <el-col :span="18">回收耗时</el-col>
                  <el-col :span="6">{{metrics.gauges['jvm.garbage.PS-Scavenge.time'].value}}ms</el-col>
                </el-row>
              </div>
            </el-card>
          </el-col>
        </el-row>
      </div>
    </el-card>
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>HTTP 请求 (事件 / 秒)</span>
      </div>
      <div>
        <p>
          使用中请求: {{metrics.counters['com.codahale.metrics.servlet.InstrumentedFilter.activeRequests'].count |numFilter0}}
          - 请求总数: {{metrics.timers['com.codahale.metrics.servlet.InstrumentedFilter.requests'].count |numFilter0}}
        </p>
        <el-table :data="reqTable" style="width: 100%">
          <el-table-column prop="t1" label="状态码"></el-table-column>
          <el-table-column prop="t2" label="次数"></el-table-column>
          <el-table-column prop="t3" label="平均数"></el-table-column>
          <el-table-column prop="t4" label="平均值 (1 min)"></el-table-column>
          <el-table-column prop="t5" label="平均值 (5 min)"></el-table-column>
          <el-table-column prop="t6" label="平均值 (15 min)"></el-table-column>
        </el-table>
      </div>
    </el-card>
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>服务统计 (时间单位为毫秒)</span>
      </div>
      <div>
        <el-table :data="servicesStats" style="width: 100%">
          <el-table-column prop="name" label="服务名称" width="400px"></el-table-column>
          <el-table-column prop="count" label="计数"></el-table-column>
          <el-table-column prop="mean" label="平均值"></el-table-column>
          <el-table-column prop="min" label="最小值"></el-table-column>
          <el-table-column prop="p50" label="p50"></el-table-column>
          <el-table-column prop="p75" label="p75"></el-table-column>
          <el-table-column prop="p95" label="p95"></el-table-column>
          <el-table-column prop="p99" label="p99"></el-table-column>
          <el-table-column prop="max" label="最大值"></el-table-column>
        </el-table>
      </div>
    </el-card>
  </div>
</template>
<script>
export default {
  data() {
    return {
      metrics: {}
    };
  },
  computed: {
    reqTable: function() {
      var reqTable = [];
      reqTable.push({
        t1: "2xx (成功)",
        t2: this.metrics.meters[
          "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.ok"
        ].count,
        t3:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.ok"
          ].mean_rate | this.numFilter2,
        t4:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.ok"
          ].m1_rate | this.numFilter2,
        t5:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.ok"
          ].m5_rate | this.numFilter2,
        t6:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.ok"
          ].m15_rate | this.numFilter2
      });
      reqTable.push({
        t1: "4xx (请求错误)",
        t2: this.metrics.meters[
          "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.notFound"
        ].count,
        t3:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.notFound"
          ].mean_rate | this.numFilter2,
        t4:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.notFound"
          ].m1_rate | this.numFilter2,
        t5:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.notFound"
          ].m5_rate | this.numFilter2,
        t6:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.notFound"
          ].m15_rate | this.numFilter2
      });
      reqTable.push({
        t1: "5xx (服务器错误)",
        t2: this.metrics.meters[
          "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.serverError"
        ].count,
        t3:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.serverError"
          ].mean_rate | this.numFilter2,
        t4:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.serverError"
          ].m1_rate | this.numFilter2,
        t5:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.serverError"
          ].m5_rate | this.numFilter2,
        t6:
          this.metrics.meters[
            "com.codahale.metrics.servlet.InstrumentedFilter.responseCodes.serverError"
          ].m15_rate | this.numFilter2
      });
      return reqTable;
    },
    servicesStats: function() {
      var servicesStats = [];
      Object.keys(this.metrics.timers).forEach(key => {
        const value = this.metrics.timers[key];
        if (key.includes("web.rest") || key.includes("service")) {
          value.name = key;
          value.mean = value.mean * 1024;
          value.min = value.min * 1024;
          value.p50 = value.p50 * 1024;
          value.p75 = value.p75 * 1024;
          value.p95 = value.p95 * 1024;
          value.p99 = value.p99 * 1024;
          value.max = value.max * 1024;
          servicesStats.push(value);
        }
      });
      return servicesStats;
    }
  },
  created() {
    this.getMetrics();
  },
  methods: {
    getMetrics() {
      this.$http({
        url: "/management/metrics",
        method: "GET"
      }).then(resp => {
        this.metrics = resp.data;
      });
    }
  },
  filters: {
    numFilter0(value) {
      let realVal = Number(value).toFixed(0);
      return Number(realVal);
    },
    numFilter2(value) {
      // 截取当前数据到小数点后两位
      let realVal = Number(value).toFixed(2); // num.toFixed(2)获取的是字符串
      return Number(realVal);
    }
  }
};
</script>
<style scoped>
.item-row {
  margin: 20px 0;
}
.box-card:not(:first-child) {
  margin-top: 15px;
}
</style>
